home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 12 / Cream of the Crop 12 (Part II) / Cream of the Crop 12 (Part II).iso / OS2 / DIKUMUD.ZIP / RECEPTIO.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-30  |  24.2 KB  |  1,036 lines

  1. /*
  2.   SillyMUD Distribution V1.1b             (c) 1993 SillyMUD Developement
  3.  
  4.   See license.doc for distribution terms.   SillyMUD is based on DIKUMUD
  5. */
  6.  
  7. #include <stdio.h>
  8. #include <sys/time.h>
  9.  
  10. #include "protos.h"
  11.  
  12. #define OBJ_SAVE_FILE "pcobjs.obj"
  13. #define OBJ_FILE_FREE "\0\0\0"
  14.  
  15. extern struct room_data *world;
  16. extern struct index_data *mob_index;
  17. extern struct index_data *obj_index;
  18. extern int top_of_objt;
  19. extern struct player_index_element *player_table;
  20. extern int top_of_p_table;
  21.  
  22.  
  23.  
  24. /* ************************************************************************
  25. * Routines used for the "Offer"                                           *
  26. ************************************************************************* */
  27.  
  28. void add_obj_cost(struct char_data *ch, struct char_data *re,
  29.                   struct obj_data *obj, struct obj_cost *cost)
  30. {
  31.   char buf[MAX_INPUT_LENGTH];
  32.   int  temp;
  33.   
  34.   /* Add cost for an item and it's contents, and next->contents */
  35.   
  36.   if (obj) {
  37.     if ((obj->item_number > -1) && (cost->ok)) {
  38.       temp = MAX(0, obj->obj_flags.cost_per_day);
  39.       cost->total_cost += temp;
  40.       if (re) {
  41.     sprintf(buf, "%30s : %d coins/day\n\r", obj->short_description, temp);
  42.     send_to_char(buf, ch);
  43.       }
  44.       cost->no_carried++;
  45.       add_obj_cost(ch, re, obj->contains, cost);
  46.       add_obj_cost(ch, re, obj->next_content, cost);
  47.     } else
  48.       if (cost->ok) {
  49.     if (re) {
  50.       act("$n tells you 'I refuse storing $p'",FALSE,re,obj,ch,TO_VICT);
  51.       cost->ok = FALSE;
  52.     } else {
  53. #if NODUPLICATES
  54. #else
  55.       act("Sorry, but $p don't keep in storage.",FALSE,ch,obj,0,TO_CHAR);
  56. #endif
  57.       cost->ok = FALSE;
  58.  
  59.     }
  60.       }
  61.   }
  62. }
  63.  
  64.  
  65. bool recep_offer(struct char_data *ch,    struct char_data *receptionist,
  66.          struct obj_cost *cost)
  67. {
  68.   int i;
  69.   char buf[MAX_INPUT_LENGTH];
  70.   
  71.   cost->total_cost = 100; /* Minimum cost */
  72.   cost->no_carried = 0;
  73.   cost->ok = TRUE; /* Use if any "-1" objects */
  74.   
  75.   add_obj_cost(ch, receptionist, ch->carrying, cost);
  76.   
  77.   for(i = 0; i<MAX_WEAR; i++)
  78.     add_obj_cost(ch, receptionist, ch->equipment[i], cost);
  79.   
  80.   if (!cost->ok)
  81.     return(FALSE);
  82.   
  83.   if (cost->no_carried == 0) {
  84.     if (receptionist)
  85.       act("$n tells you 'But you are not carrying anything?'",FALSE,receptionist,0,ch,TO_VICT);
  86.     return(FALSE);
  87.   }
  88.   
  89.   if (cost->no_carried > MAX_OBJ_SAVE) {
  90.     if (receptionist) {
  91.       sprintf(buf,"$n tells you 'Sorry, but I can't store more than %d items.",
  92.           MAX_OBJ_SAVE);
  93.       act(buf,FALSE,receptionist,0,ch,TO_VICT);
  94.     }
  95.     return(FALSE);
  96.   }
  97.  
  98.   if (HasClass(ch, CLASS_MONK)) {
  99.     if (cost->no_carried > 20) {
  100.       send_to_char("Your vows forbid you to carry more than 20 items\n\r", ch);
  101.       return(FALSE);
  102.     }
  103.   }
  104.   
  105.   if (receptionist) {
  106.  
  107. #if NEW_RENT
  108.     /* RENTAL COST ADJUSTMENT */
  109.     cost->total_cost = 100;
  110. #else
  111. #endif
  112.  
  113.     sprintf(buf, "$n tells you 'It will cost you %d coins per day'",
  114.         cost->total_cost);
  115.     act(buf,FALSE,receptionist,0,ch,TO_VICT);
  116.   
  117.     if (cost->total_cost > GET_GOLD(ch)) {
  118.       if (GetMaxLevel(ch) < LOW_IMMORTAL)
  119.     act("$n tells you 'Which I can see you can't afford'",
  120.         FALSE,receptionist,0,ch,TO_VICT);
  121.       else {
  122.     act("$n tells you 'Well, since you're a God, I guess it's okay'",
  123.         FALSE,receptionist,0,ch,TO_VICT);
  124.     cost->total_cost = 0;
  125.       }
  126.     }
  127.   }
  128.   
  129.   if ( cost->total_cost > GET_GOLD(ch) )
  130.     return(FALSE);
  131.   else
  132.     return(TRUE);
  133. }
  134.  
  135.  
  136. /* ************************************************************************
  137. * General save/load routines                                              *
  138. ************************************************************************* */
  139.  
  140. void update_file(struct char_data *ch, struct obj_file_u *st)
  141. {
  142.   FILE *fl;
  143.   char buf[200];
  144.  
  145.   /*
  146.     write the aliases and bamfs:
  147.  
  148.     */
  149.   write_char_extra(ch);
  150.  
  151.   sprintf(buf, "rent/%s", lower(ch->player.name));
  152.  
  153.   if (!(fl = fopen(buf, "w")))  {
  154.        perror("saving PC's objects");
  155.        assert(0);  
  156.   }
  157.   
  158.   rewind(fl);
  159.  
  160.   strcpy(st->owner, GET_NAME(ch));
  161.  
  162.   WriteObjs(fl, st);
  163.  
  164.   fclose(fl);
  165.   
  166. }
  167.  
  168.  
  169. /* ************************************************************************
  170. * Routines used to load a characters equipment from disk                  *
  171. ************************************************************************* */
  172.  
  173. void obj_store_to_char(struct char_data *ch, struct obj_file_u *st)
  174. {
  175.   struct obj_data *obj;
  176.   int i, j;
  177.   
  178.   void obj_to_char(struct obj_data *object, struct char_data *ch);
  179.   
  180.   for(i=0; i<st->number; i++) {
  181.     if (st->objects[i].item_number > -1 && 
  182.     real_object(st->objects[i].item_number) > -1) {
  183.       obj = read_object(st->objects[i].item_number, VIRTUAL);
  184.       obj->obj_flags.value[0] = st->objects[i].value[0];
  185.       obj->obj_flags.value[1] = st->objects[i].value[1];
  186.       obj->obj_flags.value[2] = st->objects[i].value[2];
  187.       obj->obj_flags.value[3] = st->objects[i].value[3];
  188.       obj->obj_flags.extra_flags = st->objects[i].extra_flags;
  189.       obj->obj_flags.weight      = st->objects[i].weight;
  190.       obj->obj_flags.timer       = st->objects[i].timer;
  191.       obj->obj_flags.bitvector   = st->objects[i].bitvector;
  192.  
  193. /*  new, saving names and descrips stuff */
  194.       if (obj->name)
  195.          free(obj->name);
  196.       if (obj->short_description)
  197.          free(obj->short_description);
  198.       if (obj->description)
  199.          free(obj->description);
  200.  
  201.       obj->name = (char *)malloc(strlen(st->objects[i].name)+1);
  202.       obj->short_description = (char *)malloc(strlen(st->objects[i].sd)+1);
  203.       obj->description = (char *)malloc(strlen(st->objects[i].desc)+1);
  204.  
  205.       strcpy(obj->name, st->objects[i].name);
  206.       strcpy(obj->short_description, st->objects[i].sd);
  207.       strcpy(obj->description, st->objects[i].desc);
  208. /* end of new, possibly buggy stuff */
  209.       
  210.       for(j=0; j<MAX_OBJ_AFFECT; j++)
  211.     obj->affected[j] = st->objects[i].affected[j];
  212.       
  213.       obj_to_char(obj, ch);
  214.     }
  215.   }
  216. }
  217.  
  218.  
  219. void load_char_objs(struct char_data *ch)
  220. {
  221.   FILE *fl;
  222.   bool found = FALSE;
  223.   float timegold;
  224.   struct obj_file_u st;
  225.   char buf[200];
  226.  
  227.  
  228. /*
  229.   load in aliases and poofs first
  230. */
  231.  
  232.   load_char_extra(ch);
  233.  
  234.   
  235.   sprintf(buf, "rent/%s", lower(ch->player.name));
  236.  
  237.   
  238.   /* r+b is for Binary Reading/Writing */
  239.   if (!(fl = fopen(buf, "r+b")))  {
  240.     log("Char has no equipment");
  241.     return;
  242.   }
  243.  
  244.   rewind(fl);
  245.  
  246.   if (!ReadObjs(fl, &st)) {
  247.     log("No objects found");
  248.     fclose(fl);
  249.     return;
  250.   }
  251.  
  252.   if (str_cmp(st.owner, GET_NAME(ch)) != 0) {
  253.     log("Hmm.. bad item-file write. someone is losing thier objects");
  254.     fclose(fl);
  255.     return;
  256.   }
  257.  
  258. /*
  259.   if the character has been out for 12 real hours, they are fully healed
  260.   upon re-entry.  if they stay out for 24 full hours, all affects are
  261.   removed, including bad ones.
  262. */
  263.  
  264.     if (st.last_update + 12*SECS_PER_REAL_HOUR < time(0))
  265.       RestoreChar(ch);
  266.  
  267.     if (st.last_update + 24*SECS_PER_REAL_HOUR < time(0))
  268.       RemAllAffects(ch);
  269.     
  270.     if (ch->in_room == NOWHERE &&
  271.     st.last_update + 1*SECS_PER_REAL_HOUR > time(0)) {
  272.     /* you made it back from the crash in time, 1 hour grace period. */
  273.       log("Character reconnecting.");
  274.       found = TRUE;
  275.     } else {
  276.       char    buf[MAX_STRING_LENGTH];
  277.       if (ch->in_room == NOWHERE)
  278.     log("Char reconnecting after autorent");
  279.       timegold = (int) ((st.total_cost*((float)time(0) - st.last_update)) / 
  280.             (SECS_PER_REAL_DAY));
  281.  
  282.       sprintf(buf, "Char ran up charges of %g gold in rent", timegold);
  283.       log(buf);
  284.       sprintf(buf, "You ran up charges of %g gold in rent.\n\r", timegold);
  285.       send_to_char(buf, ch);
  286.       GET_GOLD(ch) -= timegold;
  287.       found = TRUE;    
  288.       if (GET_GOLD(ch) < 0) {
  289.     log("Char ran out of money in rent");
  290.         send_to_char("You ran out of money, you deadbeat.\n\r", ch);
  291.     GET_GOLD(ch) = 0;
  292.     found = FALSE;
  293.       }
  294.     }
  295.  
  296.   fclose(fl);
  297.  
  298.   if (found)
  299.       obj_store_to_char(ch, &st);
  300.   else {
  301.     ZeroRent(GET_NAME(ch));
  302.   }
  303.   
  304.   /* Save char, to avoid strange data if crashing */
  305.   save_char(ch, AUTO_RENT);
  306.  
  307.  
  308.   
  309. }
  310.  
  311.  
  312. /* ************************************************************************
  313. * Routines used to save a characters equipment from disk                  *
  314. ************************************************************************* */
  315.  
  316. /* Puts object in store, at first item which has no -1 */
  317. void put_obj_in_store(struct obj_data *obj, struct obj_file_u *st)
  318. {
  319.   int j;
  320.   struct obj_file_elem *oe;
  321.   char buf[256];
  322.  
  323.   if (st->number>=MAX_OBJ_SAVE) {
  324.     printf("holy shit, you want to rent more than %d items?!\n", st->number);
  325.     return;
  326.   }
  327.  
  328.   oe = st->objects + st->number;
  329.   
  330.   oe->item_number = obj_index[obj->item_number].virtual;
  331.   oe->value[0] = obj->obj_flags.value[0];
  332.   oe->value[1] = obj->obj_flags.value[1];
  333.   oe->value[2] = obj->obj_flags.value[2];
  334.   oe->value[3] = obj->obj_flags.value[3];
  335.   
  336.   oe->extra_flags = obj->obj_flags.extra_flags;
  337.   oe->weight  = obj->obj_flags.weight;
  338.   oe->timer  = obj->obj_flags.timer;
  339.   oe->bitvector  = obj->obj_flags.bitvector;
  340.  
  341. /*  new, saving names and descrips stuff */
  342.       if (obj->name)
  343.          strcpy(oe->name, obj->name);
  344.       else {
  345.     sprintf(buf, "object %d has no name!", obj_index[obj->item_number].virtual);
  346.     log(buf);
  347.     
  348.       }
  349.     
  350.       if (obj->short_description)
  351.          strcpy(oe->sd, obj->short_description);
  352.       else
  353.     *oe->sd = '\0';
  354.       if (obj->description)
  355.          strcpy(oe->desc, obj->description);
  356.       else 
  357.     *oe->desc = '\0';
  358.  
  359. /* end of new, possibly buggy stuff */
  360.  
  361.  
  362.   for(j=0; j<MAX_OBJ_AFFECT; j++)
  363.     oe->affected[j] = obj->affected[j];
  364.  
  365.   st->number++;
  366. }
  367.  
  368. int contained_weight(struct obj_data *container)
  369. {
  370.   struct obj_data *tmp;
  371.   int    rval = 0;
  372.  
  373.   for (tmp = container->contains; tmp; tmp = tmp->next_content)
  374.     rval += GET_OBJ_WEIGHT(tmp);
  375.   return rval;
  376. }
  377.  
  378. /* Destroy inventory after transferring it to "store inventory" */
  379. void obj_to_store(struct obj_data *obj, struct obj_file_u *st,
  380.                   struct char_data * ch, int delete)
  381. {
  382.   static char buf[240];
  383.   
  384.   if (!obj)
  385.     return;
  386.  
  387.   obj_to_store(obj->contains, st, ch, delete);
  388.   obj_to_store(obj->next_content, st, ch, delete);
  389.     
  390.   if ((obj->obj_flags.timer < 0) && (obj->obj_flags.timer != OBJ_NOTIMER)) {
  391. #if NODUPLICATES
  392. #else
  393.     sprintf(buf, "You're told: '%s is just old junk, I'll throw it away for you.'\n\r", obj->short_description);
  394.     send_to_char(buf, ch);
  395. #endif
  396.   } else if (obj->obj_flags.cost_per_day < 0) {
  397.  
  398. #if NODUPLICATES
  399. #else
  400.     if(ch != NULL) {
  401.       sprintf(buf, "You're told: '%s is just old junk, I'll throw it away for you.'\n\r", obj->short_description);
  402.       send_to_char(buf, ch);
  403.     }
  404. #endif
  405.  
  406.     if (delete) {
  407.        if (obj->in_obj) 
  408.      obj_from_obj(obj);
  409.        extract_obj(obj);
  410.      }
  411.   } else if (obj->item_number == -1) {
  412.     if (delete) {
  413.        if (obj->in_obj) 
  414.      obj_from_obj(obj);
  415.        extract_obj(obj);
  416.      }
  417.   }else {
  418.     int weight = contained_weight(obj);
  419.           GET_OBJ_WEIGHT(obj) -= weight;
  420.     put_obj_in_store(obj, st);
  421.     GET_OBJ_WEIGHT(obj) += weight;
  422.     if (delete) {
  423.       if (obj->in_obj)
  424.     obj_from_obj(obj);
  425.       extract_obj(obj);
  426.     }
  427.   }
  428. }
  429.  
  430.  
  431.  
  432. /* write the vital data of a player to the player file */
  433. void save_obj(struct char_data *ch, struct obj_cost *cost, int delete)
  434. {
  435.   static struct obj_file_u st;
  436.   int i;
  437.   char buf[128];
  438.     
  439.   st.number = 0;
  440.   st.gold_left = GET_GOLD(ch);
  441.  
  442.   sprintf(buf, "saving %s:%d", fname(ch->player.name), GET_GOLD(ch));
  443.   slog(buf);
  444.  
  445.   st.total_cost = cost->total_cost;
  446.   st.last_update = time(0);
  447.   st.minimum_stay = 0; /* XXX where does this belong? */
  448.   
  449.   for(i=0; i<MAX_WEAR; i++)
  450.     if (ch->equipment[i]) {
  451.       if (delete) {
  452.      obj_to_store(unequip_char(ch, i), &st, ch, delete);
  453.       } else {
  454.          obj_to_store(ch->equipment[i], &st, ch, delete);
  455.       }
  456.     }
  457.   
  458.   obj_to_store(ch->carrying, &st, ch, delete);
  459.   if (delete)
  460.      ch->carrying = 0;
  461.  
  462.   update_file(ch, &st);
  463.   
  464. }
  465.  
  466.  
  467.  
  468. /* ************************************************************************
  469. * Routines used to update object file, upon boot time                     *
  470. ************************************************************************* */
  471.  
  472. void update_obj_file()
  473. {
  474.   FILE *fl, *char_file;
  475.   struct obj_file_u st;
  476.   struct char_file_u ch_st;
  477.   long i;
  478.   long days_passed, secs_lost;
  479.   char buf[200];
  480.   
  481.   int find_name(char *name);
  482.   extern int errno;
  483.  
  484.  
  485.   if (!(char_file = fopen(PLAYER_FILE, "r+"))) {
  486.     perror("Opening player file for reading. (reception.c, update_obj_file)");
  487.     assert(0);
  488.   }
  489.   
  490.   for (i=0; i<= top_of_p_table; i++) {
  491.     sprintf(buf, "rent/%s", lower(player_table[i].name));
  492.     /* r+b is for Binary Reading/Writing */
  493.     if ((fl = fopen(buf, "r+b")) != NULL) {
  494.  
  495.       if (ReadObjs(fl, &st)) {
  496.     if (str_cmp(st.owner, player_table[i].name) != 0) {
  497.        sprintf(buf, "Ack!  Wrong person written into object file! (%s/%s)", st.owner, player_table[i].name);
  498.       log(buf);
  499.       abort();
  500.     } else {
  501.       sprintf(buf, "   Processing %s[%d].", st.owner, i);
  502.       log(buf);
  503.       days_passed = ((time(0) - st.last_update) / SECS_PER_REAL_DAY);
  504.       secs_lost = ((time(0) - st.last_update) % SECS_PER_REAL_DAY);
  505.       
  506.       fseek(char_file, (long) (player_table[i].nr *
  507.                    sizeof(struct char_file_u)), 0);
  508.       fread(&ch_st, sizeof(struct char_file_u), 1, char_file);
  509.      
  510.           if (ch_st.load_room == AUTO_RENT) {  /* this person was autorented */
  511.         ch_st.load_room = NOWHERE;
  512.         st.last_update = time(0)+3600;  /* one hour grace period */
  513.  
  514.         sprintf(buf, "   Deautorenting %s", st.owner);
  515.         log(buf);
  516.  
  517. #if LIMITED_ITEMS
  518.         CountLimitedItems(&st);
  519. #endif
  520.             fseek(char_file, (long) (player_table[i].nr *
  521.                      sizeof(struct char_file_u)), 0);
  522.         fwrite(&ch_st, sizeof(struct char_file_u), 1, char_file);
  523.  
  524.         rewind(fl);
  525.         WriteObjs(fl, &st);
  526.  
  527.         fclose(fl);
  528.       } else {
  529.  
  530.         if (days_passed > 0) {
  531.           
  532.           if ((st.total_cost*days_passed) > st.gold_left) {
  533.         
  534.         sprintf(buf, "   Dumping %s from object file.", ch_st.name);
  535.         log(buf);
  536.         
  537.         ch_st.points.gold = 0;
  538.         ch_st.load_room = NOWHERE;
  539.         fseek(char_file, (long) (player_table[i].nr *
  540.                      sizeof(struct char_file_u)), 0);
  541.         fwrite(&ch_st, sizeof(struct char_file_u), 1, char_file);
  542.         
  543.         fclose(fl);
  544.         ZeroRent(ch_st.name);
  545.         
  546.           } else {
  547.         
  548.         sprintf(buf, "   Updating %s", st.owner);
  549.         log(buf);
  550.         st.gold_left  -= (st.total_cost*days_passed);
  551.         st.last_update = time(0)-secs_lost;
  552.         rewind(fl);
  553.         WriteObjs(fl, &st);
  554.         fclose(fl);
  555. #if LIMITED_ITEMS
  556.         CountLimitedItems(&st);
  557. #endif
  558.         
  559.           }
  560.         } else {
  561.           
  562. #if LIMITED_ITEMS
  563.           CountLimitedItems(&st);
  564. #endif
  565.           sprintf(buf, "  same day update on %s", st.owner);
  566.           log(buf);
  567.           rewind(fl);
  568.           WriteObjs(fl, &st);
  569.           fclose(fl);
  570.         }
  571.       }
  572.     }
  573.       }
  574.     } else {
  575.       /* do nothing */
  576.     }
  577.   }
  578.   fclose(char_file);
  579. }
  580.  
  581.  
  582. void CountLimitedItems(struct obj_file_u *st)
  583. {
  584.     int i, cost_per_day;
  585.     struct obj_data *obj;
  586.  
  587.     if (!st->owner[0]) return;  /* don't count empty rent units */
  588.  
  589.     for(i=0; i<st->number; i++) {
  590.       if (st->objects[i].item_number > -1 && 
  591.           real_object(st->objects[i].item_number) > -1) {
  592.         /*
  593.             ** eek.. read in the object, and then extract it.
  594.         ** (all this just to find rent cost.)  *sigh*
  595.             */
  596.             obj = read_object(st->objects[i].item_number, VIRTUAL);
  597.         cost_per_day = obj->obj_flags.cost_per_day;
  598.         /*
  599.             **  if the cost is > LIM_ITEM_COST_MIN, then mark before extractin
  600.             */
  601.         if (cost_per_day > LIM_ITEM_COST_MIN) {
  602.           obj_index[obj->item_number].number++;  
  603.         } else {
  604. #if NEW_RENT
  605.           if (IS_OBJ_STAT(obj, ITEM_MAGIC) ||
  606.           IS_OBJ_STAT(obj, ITEM_GLOW) ||
  607.           IS_OBJ_STAT(obj, ITEM_HUM) ||
  608.           IS_OBJ_STAT(obj, ITEM_INVISIBLE) ||
  609.           IS_OBJ_STAT(obj, ITEM_BLESS)) {
  610.         obj_index[obj->item_number].number++;  
  611.           }
  612. #endif
  613.         }
  614.         extract_obj(obj);
  615.     }
  616.     }
  617. }
  618.  
  619.  
  620. void PrintLimitedItems()
  621. {
  622. /*  int i; */
  623.   char buf[200];
  624. #if 0
  625.   for (i=0;i<=top_of_objt;i++) {
  626.     if (obj_index[i].number > 0) {
  627.       sprintf(buf, "item> %d [%d]", obj_index[i].virtual, obj_index[i].number);
  628.       log(buf);
  629.     }
  630.   }
  631. #endif
  632. }
  633.  
  634.  
  635. /* ************************************************************************
  636. * Routine Receptionist                                                    *
  637. ************************************************************************* */
  638.  
  639.  
  640.  
  641. int receptionist(struct char_data *ch, int cmd, char *arg, struct char_data *mob, int type)
  642. {
  643.   char buf[240];
  644.   struct obj_cost cost;
  645.   struct char_data *recep = 0;
  646.   struct char_data *temp_char;
  647.   sh_int save_room;
  648.   sh_int action_tabel[9];
  649.   
  650.   
  651.   if (!ch->desc)
  652.     return(FALSE); /* You've forgot FALSE - NPC couldn't leave */
  653.  
  654.    action_tabel[0] = 23;
  655.    action_tabel[1] = 24;
  656.    action_tabel[2] = 36;
  657.    action_tabel[3] = 105;
  658.    action_tabel[4] = 106;
  659.    action_tabel[5] = 109;
  660.    action_tabel[6] = 111;
  661.    action_tabel[7] = 142;
  662.    action_tabel[8] = 147;
  663.  
  664.   
  665.   for (temp_char = real_roomp(ch->in_room)->people; (temp_char) && (!recep);
  666.        temp_char = temp_char->next_in_room)
  667.     if (IS_MOB(temp_char))
  668.       if (mob_index[temp_char->nr].func == receptionist)
  669.     recep = temp_char;
  670.   
  671.   if (!recep) {
  672.     log("No_receptionist.\n\r");
  673.     assert(0);
  674.   }
  675.   
  676.   if (IS_NPC(ch))
  677.     return(FALSE);
  678.   
  679.   if ((cmd != 92) && (cmd != 93)) {
  680.     if (!cmd) {
  681.       if (recep->specials.fighting) {
  682.     return(citizen(recep,0,"",mob,type));
  683.       }
  684.     }
  685.     if (!number(0, 30))
  686.       do_action(recep, "", action_tabel[number(0,8)]);
  687.     return(FALSE);
  688.   }
  689.   
  690.   if (!AWAKE(recep)) {
  691.     act("$e isn't able to talk to you...", FALSE, recep, 0, ch, TO_VICT);
  692.     return(TRUE);
  693.   }
  694.   
  695.   if (!CAN_SEE(recep, ch))     {
  696.       act("$n says, 'I just can't deal with people I can't see!'", FALSE, recep, 0, 0, TO_ROOM);
  697.       act("$n bursts into tears", FALSE, recep, 0, 0, TO_ROOM);
  698.       return(TRUE);
  699.     }
  700.   
  701.   if (cmd == 92) { /* Rent  */
  702.     if (recep_offer(ch, recep, &cost)) {
  703.       
  704.       act("$n stores your stuff in the safe, and helps you into your chamber.",
  705.       FALSE, recep, 0, ch, TO_VICT);
  706.       act("$n helps $N into $S private chamber.",FALSE, recep,0,ch,TO_NOTVICT);
  707.       
  708.       save_obj(ch, &cost,1);
  709.       save_room = ch->in_room;
  710.  
  711.       if (ch->specials.start_room != 2) /* hell */
  712.     ch->specials.start_room = save_room;
  713.  
  714.       extract_char(ch);  /* you don't delete CHARACTERS when you extract
  715.                 them */
  716.       save_char(ch, save_room);
  717.       ch->in_room = save_room;
  718.  
  719.     }
  720.     
  721.   } else {         /* Offer */
  722.     recep_offer(ch, recep, &cost);
  723.     act("$N gives $n an offer.", FALSE, ch, 0, recep, TO_ROOM);
  724.   }
  725.   
  726.   return(TRUE);
  727. }
  728.  
  729.  
  730. /*
  731.     removes a player from the list of renters
  732. */
  733.  
  734. void zero_rent( struct char_data *ch) 
  735. {
  736.  
  737.   if (IS_NPC(ch))
  738.     return;
  739.  
  740.   ZeroRent(GET_NAME(ch));
  741.  
  742. }
  743.  
  744. void ZeroRent( char *n)
  745. {
  746.   FILE *fl;
  747.   char buf[200];
  748.  
  749.   sprintf(buf, "rent/%s", lower(n));
  750.  
  751.   if (!(fl = fopen(buf, "w"))) {
  752.     perror("saving PC's objects");
  753.     assert(0);
  754.   }
  755.   
  756.   fclose(fl);
  757.   return;
  758.   
  759. }
  760.  
  761. int ReadObjs( FILE *fl, struct obj_file_u *st)
  762. {
  763.   int i;
  764.   char buf[128];
  765.  
  766.   if (feof(fl)) {
  767.     fclose(fl);
  768.     return(FALSE);
  769.   }
  770.  
  771.   fread(st->owner, sizeof(st->owner), 1, fl);
  772.   if (feof(fl)) {
  773.     fclose(fl);
  774.     return(FALSE);
  775.   }
  776.   fread(&st->gold_left, sizeof(st->gold_left), 1, fl);
  777.   if (feof(fl)) {
  778.     fclose(fl);
  779.     return(FALSE);
  780.   }
  781.   fread(&st->total_cost, sizeof(st->total_cost), 1, fl);
  782.   if (feof(fl)) {
  783.     fclose(fl);
  784.     return(FALSE);
  785.   }
  786.   fread(&st->last_update, sizeof(st->last_update), 1, fl);
  787.   if (feof(fl)) {
  788.     fclose(fl);
  789.     return(FALSE);
  790.   }
  791.   fread(&st->minimum_stay, sizeof(st->minimum_stay), 1, fl);
  792.   if (feof(fl)) {
  793.     fclose(fl);
  794.     return(FALSE);
  795.   }
  796.   fread(&st->number, sizeof(st->number), 1, fl);
  797.   if (feof(fl)) {
  798.     fclose(fl);
  799.     return(FALSE);
  800.   }
  801.    
  802.   for (i=0;i<st->number;i++) {
  803.      fread(&st->objects[i], sizeof(struct obj_file_elem), 1, fl);
  804.   }
  805.  
  806. }
  807.  
  808. int WriteObjs( FILE *fl, struct obj_file_u *st)
  809. {
  810.   int i;
  811.   char buf[128];
  812.  
  813.   fwrite(st->owner, sizeof(st->owner), 1, fl);
  814.   fwrite(&st->gold_left, sizeof(st->gold_left), 1, fl);
  815.   fwrite(&st->total_cost, sizeof(st->total_cost), 1, fl);
  816.   fwrite(&st->last_update, sizeof(st->last_update), 1, fl);
  817.   fwrite(&st->minimum_stay, sizeof(st->minimum_stay), 1, fl);
  818.   fwrite(&st->number, sizeof(st->number), 1, fl);
  819.    
  820.   for (i=0;i<st->number;i++) {
  821.      fwrite(&st->objects[i], sizeof(struct obj_file_elem), 1, fl);
  822.   }
  823. }
  824.  
  825.  
  826. void load_char_extra(struct char_data *ch)
  827. {
  828.   FILE *fp;
  829.   char buf[80];
  830.   char line[260];
  831.   char  tmp[260];
  832.   char *p, *s, *chk;
  833.   int n;
  834.  
  835.   sprintf(buf, "rent/%s.aux", GET_NAME(ch));
  836.  
  837.   /*
  838.     open the file.. read in the lines, use them as the aliases and
  839.     poofin and outs, depending on tags:
  840.  
  841.     format:
  842.  
  843.     <id>:string
  844.  
  845.   */
  846.  
  847.   if ((fp = fopen(buf, "r")) == NULL) {
  848.     return;  /* nothing to look at */
  849.   }
  850.  
  851.   while (!feof(fp)) {
  852.     chk = fgets(line, 260, fp);
  853.  
  854.     if (chk) {
  855.       p = (char *)strtok(line, ":");
  856.       s = (char *)strtok(0, "\0");
  857.       if (p) {
  858.     if (!strcmp(p,"out")) { /*setup bamfout */
  859.       do_bamfout(ch, s, 0);
  860.     } else if (!strcmp(p, "in")) { /* setup bamfin */
  861.       do_bamfin(ch, s, 0);
  862.     } else if (!strcmp(p, "zone")) { /* set zone permisions */
  863.           GET_ZONE(ch) = atoi(s);
  864.     } else{
  865.       if (s) {
  866.         s[strlen(s)]= '\0';
  867.         n = atoi(p);
  868.         if (n >=0 && n <= 9) {  /* set up alias */
  869.           sprintf(tmp, "%d %s", n, s+1);
  870.           do_alias(ch, tmp, 260);
  871.         }
  872.       }
  873.     }
  874.       }
  875.     } else {
  876.       break;
  877.     }
  878.   }
  879.   fclose(fp);
  880. }
  881.  
  882. void write_char_extra( struct char_data *ch)
  883. {
  884.   FILE *fp;
  885.   char buf[80];
  886.   int i;
  887.  
  888.   sprintf(buf, "rent/%s.aux", GET_NAME(ch));
  889.  
  890.   /*
  891.     open the file.. read in the lines, use them as the aliases and
  892.     poofin and outs, depending on tags:
  893.  
  894.     format:
  895.  
  896.     <id>:string
  897.  
  898.   */
  899.  
  900.   if ((fp = fopen(buf, "w")) == NULL) {
  901.     return;  /* nothing to write */
  902.   }
  903.  
  904.   if (IS_IMMORTAL(ch)) {
  905.     if (ch->specials.poofin) {
  906.       fprintf(fp, "in: %s\n", ch->specials.poofin);
  907.     }
  908.     if (ch->specials.poofout) {
  909.       fprintf(fp, "out: %s\n", ch->specials.poofout);
  910.     }
  911.     fprintf(fp, "zone: %d\n", GET_ZONE(ch));
  912.   }
  913.  
  914.   if (ch->specials.A_list) {
  915.     for (i=0;i<10;i++) {
  916.       if (GET_ALIAS(ch, i)) {
  917.     fprintf(fp, "%d: %s\n", i, GET_ALIAS(ch, i));
  918.       }
  919.     }
  920.   }
  921.   fclose(fp);
  922. }
  923.  
  924.  
  925. void obj_store_to_room(int room, struct obj_file_u *st)
  926. {
  927.   struct obj_data *obj;
  928.   int i, j;
  929.   
  930.   
  931.   for(i=0; i<st->number; i++) {
  932.     if (st->objects[i].item_number > -1 && 
  933.     real_object(st->objects[i].item_number) > -1) {
  934.       obj = read_object(st->objects[i].item_number, VIRTUAL);
  935.       obj->obj_flags.value[0] = st->objects[i].value[0];
  936.       obj->obj_flags.value[1] = st->objects[i].value[1];
  937.       obj->obj_flags.value[2] = st->objects[i].value[2];
  938.       obj->obj_flags.value[3] = st->objects[i].value[3];
  939.       obj->obj_flags.extra_flags = st->objects[i].extra_flags;
  940.       obj->obj_flags.weight      = st->objects[i].weight;
  941.       obj->obj_flags.timer       = st->objects[i].timer;
  942.       obj->obj_flags.bitvector   = st->objects[i].bitvector;
  943.  
  944. /*  new, saving names and descrips stuff */
  945.       if (obj->name)
  946.          free(obj->name);
  947.       if (obj->short_description)
  948.          free(obj->short_description);
  949.       if (obj->description)
  950.          free(obj->description);
  951.  
  952.       obj->name = (char *)malloc(strlen(st->objects[i].name)+1);
  953.       obj->short_description = (char *)malloc(strlen(st->objects[i].sd)+1);
  954.       obj->description = (char *)malloc(strlen(st->objects[i].desc)+1);
  955.  
  956.       strcpy(obj->name, st->objects[i].name);
  957.       strcpy(obj->short_description, st->objects[i].sd);
  958.       strcpy(obj->description, st->objects[i].desc);
  959. /* end of new, possibly buggy stuff */
  960.       
  961.       for(j=0; j<MAX_OBJ_AFFECT; j++)
  962.     obj->affected[j] = st->objects[i].affected[j];
  963.       
  964.       obj_to_room2(obj, room);
  965.     }
  966.   }
  967.   free(st->objects);
  968.  
  969. }
  970.  
  971. void load_room_objs(int room)
  972. {
  973.   FILE *fl;
  974.   struct obj_file_u st;
  975.   char buf[200];
  976.   
  977.   sprintf(buf, "world/%d", room);
  978.  
  979.   
  980.   /* r+b is for Binary Reading/Writing */
  981.   if (!(fl = fopen(buf, "r+b")))  {
  982.     log("Room has no equipment");
  983.     return;
  984.   }
  985.  
  986.   rewind(fl);
  987.  
  988.   if (!ReadObjs(fl, &st)) {
  989.     log("No objects found");
  990.     fclose(fl);
  991.     return;
  992.   }
  993.  
  994.   fclose(fl);
  995.  
  996.   obj_store_to_room(room, &st);
  997.   save_room(room);
  998. }
  999.  
  1000. void save_room(int room)
  1001. {
  1002.  struct obj_file_u st;
  1003.  struct obj_data *obj;
  1004.  struct room_data *rm = 0;
  1005.  char buf[255];
  1006.  static int last_room = -1;
  1007.  static FILE *f1 = 0;
  1008.  
  1009.  rm = real_roomp(room);
  1010.  
  1011.  obj = rm->contents;
  1012.  sprintf(buf, "world/%d", room);
  1013.  st.number = 0;
  1014.  
  1015.  if(obj) {
  1016.    if (room != last_room) {
  1017.      if (f1)
  1018.        fclose(f1);
  1019.      f1 = fopen(buf, "w");
  1020.    }
  1021.    if (!f1) 
  1022.      return;
  1023.  
  1024.    rewind(f1);
  1025.    obj_to_store(obj, &st, NULL, 0);
  1026.    sprintf(buf, "Room %d", room);
  1027.    strcpy(st.owner, buf);
  1028.    st.gold_left = 0;
  1029.    st.total_cost = 0;
  1030.    st.last_update = 0;
  1031.    st.minimum_stay = 0;
  1032.    WriteObjs(f1, &st);
  1033.   }
  1034. }
  1035.  
  1036.